package com.taysear.parcel;

import java.util.Set;

import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;

import com.taysear.parcel.domain.Account;
import com.taysear.parcel.domain.Bus;
import com.taysear.parcel.domain.Country;
import com.taysear.parcel.domain.Currency;
import com.taysear.parcel.domain.Customer;
import com.taysear.parcel.domain.Employee;
import com.taysear.parcel.domain.EmployeeStatus;
import com.taysear.parcel.domain.EmployeeType;
import com.taysear.parcel.domain.ParcelAction;
import com.taysear.parcel.domain.ParcelStatus;
import com.taysear.parcel.domain.ParcelType;
import com.taysear.parcel.domain.PaymentMode;
import com.taysear.parcel.domain.Role;
import com.taysear.parcel.domain.Route;
import com.taysear.parcel.domain.RouteTime;
import com.taysear.parcel.domain.Station;
import com.taysear.parcel.domain.StationStatus;
import com.taysear.parcel.domain.Substation;
import com.taysear.parcel.domain.Time;
import com.taysear.parcel.domain.User;
import com.taysear.parcel.fieldfactory.AccountFieldFactory;
import com.taysear.parcel.fieldfactory.BusFieldFactory;
import com.taysear.parcel.fieldfactory.CountryFieldFactory;
import com.taysear.parcel.fieldfactory.CurrencyFieldFactory;
import com.taysear.parcel.fieldfactory.CustomerFieldFactory;
import com.taysear.parcel.fieldfactory.EmployeeFieldFactory;
import com.taysear.parcel.fieldfactory.EmployeeTypeFieldFactory;
import com.taysear.parcel.fieldfactory.ParcelTypeFieldFactory;
import com.taysear.parcel.fieldfactory.PaymentModeFieldFactory;
import com.taysear.parcel.fieldfactory.RouteFieldFactory;
import com.taysear.parcel.fieldfactory.RouteTimeFieldFactory;
import com.taysear.parcel.fieldfactory.StationFieldFactory;
import com.taysear.parcel.fieldfactory.SubstationFieldFactory;
import com.taysear.parcel.fieldfactory.TimeFieldFactory;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.addon.jpacontainer.fieldfactory.FieldFactory;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Tree;

public class AutoCrudViews extends HorizontalSplitPanel {
	ParcelApplication app;
	private Subject currentUser;
	
	public AutoCrudViews(ParcelApplication app) {
		this.app = app;
		this.currentUser = SecurityUtils.getSubject();
		Tree navTree = new Tree();
		navTree.addListener(new Property.ValueChangeListener() {
			@Override
			public void valueChange(ValueChangeEvent event) {
				BasicCrudView cv = (BasicCrudView) event.getProperty().getValue();
				cv.refreshContainer();
				setSecondComponent(cv);
			}
		});
		navTree.setSelectable(true);
		navTree.setNullSelectionAllowed(false);
		navTree.setImmediate(true);

		setSplitPosition(200, HorizontalSplitPanel.UNITS_PIXELS);
		addComponent(navTree);

		// add a basic crud view for all entities known by the JPA
		// implementation, most often this is not desired and developers
		// should just list those entities they want to have editors for
		Metamodel metamodel = JPAContainerFactory
				.createEntityManagerForPersistenceUnit(app.PERSISTENCE_UNIT)
				.getEntityManagerFactory().getMetamodel();
		Set<EntityType<?>> entities = metamodel.getEntities();
		for (EntityType<?> entityType : entities) {
			Class<?> javaType = entityType.getJavaType();
			/*if(javaType == Roles.class) {
				BasicCrudView2 view = buildVieuw(navTree, javaType, new RolesFieldFactory(app));
			}*/
			if(javaType == Bus.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_BUS)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new BusFieldFactory(app));
				view.setVisibleTableProperties("registrationNumber", "make", "model");
				view.setVisibleAddFormProperties("registrationNumber", "make", "model", "tonnage", "millage", "chasisNumber", "nextService", "lastfuel", "available", "availableDate", "conditionDescription", "conditionDescriptionDate", "fromStation", "toStation");
				view.setVisibleEditFormProperties("busId", "registrationNumber", "make", "model", "tonnage", "millage", "chasisNumber", "nextService", "lastfuel", "available", "availableDate", "conditionDescription", "conditionDescriptionDate", "fromStation", "toStation");
			}
			if(javaType == Country.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_COUNTRY)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new CountryFieldFactory(app));
				view.setVisibleTableProperties("name", "vat", "currency");
				view.setVisibleAddFormProperties("name", "vat", "currency");
				view.setVisibleEditFormProperties("countryId", "name", "vat", "currency");
			}
			if(javaType == Customer.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_CUSTOMER)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new CustomerFieldFactory());
				view.setVisibleTableProperties("firstname", "lastname", "city", "tel1");
				view.setVisibleAddFormProperties("firstname", "lastname", "idNumber", "address", "postcode", "city", "tel1");
				view.setVisibleEditFormProperties("customerId", "firstname", "lastname", "idNumber", "address", "postcode", "city", "tel1");
			}
			if(javaType == Account.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_ACCOUNT)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new AccountFieldFactory(app));
				view.setVisibleTableProperties("name", "customer", "accountStatus");
				view.setVisibleAddFormProperties("name", "customer", "openingBalance", "accountStatus");
				view.setVisibleEditFormProperties("accountId", "name", "customer", "accountStatus");
			}
			if(javaType == Currency.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_CURRENCY)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new CurrencyFieldFactory());
				view.setVisibleTableProperties("currencyId", "name");
				view.setVisibleAddFormProperties("name");
				view.setVisibleEditFormProperties("currencyId", "name");
			}
			if(javaType == EmployeeType.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_EMPLOYEETYPE)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new EmployeeTypeFieldFactory());
				view.setVisibleTableProperties("employeeTypeId", "description");
				view.setVisibleAddFormProperties("description");
				view.setVisibleEditFormProperties("employeeTypeId", "description");
			}
			/*if(javaType == EmployeeStatus.class) {
				BasicCrudView2 view = buildVieuw(navTree, javaType, new EmployeeStatusFieldFactory());
				view.setVisibleTableProperties("employeeStatusId", "description");
				view.setVisibleAddFormProperties("description");
				view.setVisibleEditFormProperties("employeeStatusId", "description");
			}*/
			Boolean allEmp = currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_ALL_EMPLOYEE);
			Boolean stEmp = currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_STATION_EMPLOYEE);
			Boolean subEmp = currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_SUBSTATION_EMPLOYEE);
			if(javaType == Employee.class && (allEmp | stEmp | subEmp)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new EmployeeFieldFactory(app));
				view.setVisibleTableProperties("firstname", "lastname", "employeeType", "employeeStatus", "station", "substation");
				view.setVisibleAddFormProperties("firstname", "lastname", "idNumber", "drivingLicenceNumber", "drivingLicenceExpireDate", "bloodgroup", "address", "postcode", "city", "tel1", "tel2", "employeeType", "dob", "employeeStatus", "terminatedDate", "gender", "station", "substation");
				view.setVisibleEditFormProperties("employeeId", "firstname", "lastname", "idNumber", "drivingLicenceNumber", "drivingLicenceExpireDate", "bloodgroup", "address", "postcode", "city", "tel1", "tel2", "employeeType", "joinDate", "dob", "employeeStatus", "terminatedDate", "gender", "station", "substation");
			}
			/*if(javaType == StationStatus.class) {
				BasicCrudView2 view = buildVieuw(navTree, javaType, new StationStatusFieldFactory());
				view.setVisibleTableProperties("id", "description");
				view.setVisibleAddFormProperties("description");
				view.setVisibleEditFormProperties("id", "description");
			}*/
			if(javaType == Station.class) {
				BasicCrudView view = buildVieuw(navTree, javaType, new StationFieldFactory(app));
				view.setVisibleTableProperties("code", "name", "stationStatus");
				view.setVisibleAddFormProperties("code", "name", "stationStatus", "country");
				view.setVisibleEditFormProperties("stationId", "name", "stationStatus");
			}
			if(javaType == Substation.class) {
				BasicCrudView view = buildVieuw(navTree, javaType, new SubstationFieldFactory(app));
				view.setVisibleTableProperties("code", "substationNumber", "waybillNumber", "name", "station", "stationStatus");
				view.setVisibleAddFormProperties("code", "name", "station", "stationStatus");
				view.setVisibleEditFormProperties("substationId", "name", "stationStatus");
			}
			/*if(javaType == ParcelStatus.class) {
				BasicCrudView2 view = buildVieuw(navTree, javaType, new ParcelStatusFieldFactory());
				view.setVisibleTableProperties("parcelStatusId", "description");
				view.setVisibleAddFormProperties("description");
				view.setVisibleEditFormProperties("parcelStatusId", "description");
			}*/
			if(javaType == ParcelType.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_PARCELTYPE)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new ParcelTypeFieldFactory());
				view.setVisibleTableProperties("parcelTypeId", "description");
				view.setVisibleAddFormProperties("description");
				view.setVisibleEditFormProperties("parcelTypeId", "description");
			}
			/*if(javaType == ParcelAction.class) {
				BasicCrudView2 view = buildVieuw(navTree, javaType, new ParcelActionFieldFactory());
				view.setVisibleTableProperties("parcelActionId", "description");
				view.setVisibleAddFormProperties("description");
				view.setVisibleEditFormProperties("parcelActionId", "description");
			}*/
			if(javaType == PaymentMode.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_PAUMENTMODE)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new PaymentModeFieldFactory());
				view.setVisibleTableProperties("paymentModeId", "description");
				view.setVisibleAddFormProperties("description");
				view.setVisibleEditFormProperties("paymentModeId", "description");
			}
			if(javaType == Route.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_ROUTE)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new RouteFieldFactory(app));
				view.setVisibleTableProperties("routeId", "routeStart", "routeEnd", "routeStatus");
				view.setVisibleAddFormProperties("routeStart", "routeEnd", "routeStatus");
				view.setVisibleEditFormProperties("routeId", "routeStart", "routeEnd", "routeStatus");
				view.showRouteDetailButton();
			}
			if(javaType == RouteTime.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_ROUTE)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new RouteTimeFieldFactory(app));
				view.setVisibleTableProperties("routeTimeId", "route", "time", "isActive");
				view.setVisibleAddFormProperties("route", "time", "isActive");
				view.setVisibleEditFormProperties("routeTimeId", "isActive");
			}
			if(javaType == Time.class && currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_ROUTE)) {
				BasicCrudView view = buildVieuw(navTree, javaType, new TimeFieldFactory());
				view.setVisibleTableProperties("timeId", "reportingTime", "departureTime", "amPm");
				view.setVisibleAddFormProperties("reportingTime", "departureTime", "amPm");
				view.setVisibleEditFormProperties("timeId", "reportingTime", "departureTime", "amPm");
			}
		}

		// select first entity view
		navTree.setValue(navTree.getItemIds().iterator().next());
	}
	
	private BasicCrudView buildVieuw(Tree navTree, Class<?> javaType, FieldFactory fieldFactory){
		BasicCrudView view = new BasicCrudView(app, javaType, app.PERSISTENCE_UNIT, fieldFactory);
		navTree.addItem(view);
		navTree.setItemCaption(view, view.getCaption());
		navTree.setChildrenAllowed(view, false);
		return view;
	}
}
